//
//  CAIFMDB.h
//  Runner
//
//  Created by simon on 2021/8/31.
//

#import <Foundation/Foundation.h>



NS_ASSUME_NONNULL_BEGIN

@interface CAIFMDB : NSObject


/**
 * Returns 单列数据库
 */
@property (nonatomic, class, readonly, nullable) CAIFMDB *sharedInstance;


/**
 构造方法创建数据库
 
 @param dbName 数据库的名称 如: @"CAIFMDB.db"
        dbPath 数据库的路径, 如果dbPath = nil, 则路径默认为NSDocumentDirectory
 */
- (nullable instancetype)initWithDBName:(nullable NSString *)dbName;
- (nullable instancetype)initWithDBName:(nullable NSString *)dbName path:(nullable NSString *)dbPath;




/// 根据字典创建table
/// @param tableName 表的名称，不能为空；
/// @param parameters SQLite表的key-value，key是column定义名，value是数据类型；如果为nil或空，则创建的是空表，如@{@"name":@"TEXT",@"age":@"INTEGER"}；
/// @param error 错误信息
- (BOOL)createTable:(NSString *)tableName
                dic:(nullable NSDictionary *)parameters
              error:(NSError * __autoreleasing *)error;


/// 根据字典创建table
/// @param tableName 表的名称，不能为空；
/// @param parameters SQLite表的key-value，key是column定义名，value是数据类型；如果为nil或空，则创建的是空表，如@{@"name":@"TEXT",@"age":@"INTEGER"}；
/// @param nameArr parameters中除外的key，不进行创建column
/// @param error 错误信息
- (BOOL)createTable:(NSString *)tableName
                dic:(nullable NSDictionary *)parameters
        excludeName:(nullable NSArray<NSString *> *)nameArr
              error:(NSError * __autoreleasing *)error;


/**
 增加-向表中插入数据

 @param tableName 表的名称，不能为空；
 @param parameters 要插入的数据,dictionary(格式:@{@"name":@"小李"}) key必须在表中的column name
 @return 是否插入成功
 */
- (BOOL)insertTable:(NSString *)tableName dic:(id)parameters;


/**
 删除：根据条件删除表中数据

 @param tableName 表的名称
 @param format 条件语句, 如:@"where name = 'AA'"
 @return 是否删除成功
 */
- (BOOL)deleteTable:(NSString *)tableName whereFormat:(NSString *)format,...;


/// 清空表
/// @param tableName 表的名称
- (BOOL)deleteTable:(NSString *)tableName;


/// 更改-根据条件更改表中数据
/// @param tableName 表的名称
/// @param parameters 要更改的数据,dictionary(格式:@{@"name":@"张三"})
/// @param format 条件语句, 如:@"where name = '小李'"；如果是nil，则表中每条数据的指定key都修改为parameters的指定value；
/// @return 是否更改成功
- (BOOL)updateTable:(NSString *)tableName
                dic:(NSDictionary *)parameters
        whereFormat:(nullable NSString *)format, ...;

/// 查找-根据条件及指定参数类型查找表中数据；
/// @param tableName 表的名称
/// @param parameters 查找需要返回的指定参数和类型：@{@"name1":@"TEXT",@"age":@"INTEGER"}
/// @param format 条件语句, 如:@"where name = '小李'",
- (NSArray *)fetchTable:(NSString *)tableName
                      dic:(NSDictionary *)parameters
              whereFormat:(nullable NSString *)format, ...;

/// 删除表
/// @param tableName 表的名称
- (BOOL)dropTable:(NSString *)tableName;


/// 检查在db中是否存在指定表？
/// @param tableName 表名
- (BOOL)tableExists:(NSString *)tableName;

///`表中共有多少条数据
- (int)tableItemCount:(NSString *)tableName;

- (NSArray *)getColumnArr:(NSString *)tableName;

/// 获取model的key和value
- (NSDictionary *)getModelPropertyKeyValue:(id)model tableName:(NSString *)tableName;

// =============================   线程安全操作    ===============================

/**
 将操作语句放入block中即可保证线程安全, 如:
 
 Person *p = [[Person alloc] init];
 p.name = @"小李";
 [db executeInDatabase:^{
 [db insertTable:@"User" model:p];
 }];
 */
- (void)executeInDatabase:(void(^)(void))block;


@end



@interface CAIFMDB (JSONObject)

/// 创建表：只有一个column：（data TEXT）
/// @param tableName 表的名称，不能为空；
/// @param model 模型数据
/// @param error 错误信息
- (BOOL)createGeneralTable:(NSString *)tableName
                     model:(nullable id)model
                     error:(NSError * __autoreleasing *)error;

///// 增加：把model数据按json数据字符串插入到通用表
///// @param tableName 表的名称
///// @param model 模型对象
//- (BOOL)insertTable:(NSString *)tableName
//              model:(id)model
//              error:(NSError * __autoreleasing *)error;
//
//- (BOOL)insertEncodeWithTable:(NSString *)tableName
//                            model:(id)model
//                            error:(NSError * __autoreleasing *)error;
//
/// 更改：更改表中数据
/// @param tableName 表的名称
/// @param model 模型对象。
/// @return 是否更改成功
- (BOOL)updateTable:(NSString *)tableName
              model:(id)model;

- (BOOL)updateEncodeTable:(NSString *)tableName
                    model:(id)model;



- (BOOL)setTable:(NSString *)tableName
           model:(id)model
           error:(NSError * __autoreleasing *)error;

- (BOOL)setEncodeTable:(NSString *)tableName
                 model:(id)model
                 error:(NSError * __autoreleasing *)error;
/**
 查找-查找表中所有数据(目前只支持获取model数据，不支持model数组)

 @param tableName 表的名称
 @param cls 需要返回的根类
 @return 将结果存入array,数组中的元素的类型为parameters的类型
 */
- (NSArray *)fetchTable:(NSString *)tableName modelClass:(Class)cls;

- (NSArray *)fetchDecodeTable:(NSString *)tableName modelClass:(Class)cls;
@end

NS_ASSUME_NONNULL_END
